import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';

class SSEClient {
  final Dio _dio;
  final String url;
  final Map<String, dynamic> _headers;
  StreamController<SSEEvent> _controller = StreamController.broadcast();
  CancelToken? _cancelToken;
  int _reconnectAttempts = 3;

  SSEClient({
    required this.url,
    Dio? dio,
    Map<String, dynamic>? headers,
  })  : _dio = dio ?? Dio(),
        _headers = headers ?? {} {
    _headers[HttpHeaders.acceptHeader] = 'text/event-stream';
    _headers[HttpHeaders.cacheControlHeader] = 'no-cache';
  }

  Stream<SSEEvent> get stream => _controller.stream;

  Future<void> connect(Map<String,dynamic> params) async {
    while (_reconnectAttempts < 5) { // 最大重试次数
      try {
        await _connectInternal(params);
        break;
      } catch (e) {
        _controller.addError(e);
        await Future.delayed(Duration(seconds: _reconnectAttempts * 2));
        _reconnectAttempts++;
      }
    }
  }

  Future<void> _connectInternal(Map<String,dynamic> params) async {
    _cancelToken = CancelToken();
    final response = await _dio.post<ResponseBody>(
      url,
      options: Options(
        headers: _headers,
        responseType: ResponseType.stream,
      ),
      cancelToken: _cancelToken,
      data: params
    );

    /*await for (String value in response.data!.stream.transform(StreamTransformer.fromHandlers(
      handleData: (bytes, sink) {
           print('=====response.data======>${utf8.decode(bytes)}');
           try {
             sink.add(utf8.decode(bytes));
           } on FormatException catch (e) {
             print('解码错误：$e');
             // 处理错误，比如使用备用编码或记录日志
           }

      },
    ))) {
      _processChunk(value);
    }*/

    response.data!.stream.transform(StreamTransformer.fromHandlers(
      handleData: (bytes, sink) {
        print('=====response.data======>${utf8.decode(bytes)}');
        try {
          sink.add(utf8.decode(bytes));
        } on FormatException catch (e) {
          print('解码错误：$e');
          // 处理错误，比如使用备用编码或记录日志
        }

      },
    )).listen((v){
      _processChunk(v as String);
    });
    /*await for (String value in response.data!.stream.transform(StreamTransformer.fromHandlers(
      handleData: (bytes, sink) {
           print('=====response.data======>${utf8.decode(bytes)}');
           try {
             sink.add(utf8.decode(bytes));
           } on FormatException catch (e) {
             print('解码错误：$e');
             // 处理错误，比如使用备用编码或记录日志
           }

      },
    ))) {
      _processChunk(value);
    }*/
  }

  void _processChunk(String chunk) {
    // final lines = chunk.split('\n');
    /*var line = chunk.trim();
    print('_processChunk======>${chunk}');
    line = line.replaceAll('data:', '');
    try {
      if(line.contains('code":200')) {
        print('json decode line ------> ${line}');
        Map<String,dynamic> map = json.decode(line);
        Map<String,dynamic> contentMap = map['data']['Choices'][0];
        String content = contentMap['Delta']['Content'];
        String reasoningContent = contentMap['FinishReason'];
        SSEEvent currentEvent = SSEEvent(reasoningContent == '' ? 'normal': reasoningContent, content, '');
        *//* currentEvent.event = reasoningContent == '' ? 'normal': reasoningContent;
         currentEvent.data = content;*//*
        _controller.add(currentEvent);
      }
    } catch(e) {
      print('my catch erros: ${e}');
    }*/
    final lines = chunk.split('\n');
    SSEEvent currentEvent = SSEEvent();
    for (final line in lines) {
      print('------- line  -------------> ${line}');
      if (line.startsWith('data:')) {
        currentEvent.data = line.substring(5).trim();
      } else if(line.length > 20) {
        currentEvent.data = line;
      } else if (line.startsWith('event:')) {
        currentEvent.event = line.substring(6).trim();
      } else if (line.startsWith('id:')) {
        currentEvent.id = line.substring(3).trim();
      } else if (line.isEmpty) {
        if (currentEvent.data != null) {
          _controller.add(currentEvent);
          currentEvent = SSEEvent();
        }
      }
    }


    /*SSEEvent currentEvent = SSEEvent();

    for (final line in lines) {
      if (line.startsWith('data:')) {
        currentEvent.data = line.substring(5).trim();
      } else if (line.startsWith('event:')) {
        currentEvent.event = line.substring(6).trim();
      } else if (line.startsWith('id:')) {
        currentEvent.id = line.substring(3).trim();
      } else if (line.isEmpty) {
        if (currentEvent.data != null) {
          _controller.add(currentEvent);
          currentEvent = SSEEvent();
        }
      }
    }*/



  }

  void disconnect() {
    _cancelToken?.cancel();
    _controller.close();
  }
}

class SSEEvent {
  String? event;
  String? data;
  String? id;

  SSEEvent({this.data,this.event,this.id});

  @override
  String toString() => 'SSEEvent{event: $event, data: $data, id: $id}';
}